home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
526-550
/
disk_542
/
chemnimate
/
cmtsource.lzh
/
parser11.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-27
|
14KB
|
570 lines
/****************************************************************
* *
* CheMnimaTe to Animate Chemical Reactions *
* *
* *
* this program is written to show how molecules *
* are in 3-d and how mechanisms work. *
* *
* *
* *
* *
*==============================================================*
*Vers. Date Author Comment *
*sk1 22Mar91 KvGend started working on it. *******
*sk5 24Mar91 KvGend is now able to rotate some complicated formula*
*sk9 30Mar91 KvGend Now accepts scripts. Is able to play *******
* along with penicilline *
*ch6 09Apr91 KvGend Scripts now use full commands. *
*pars6 08May91 KvGend Tokenized the whole stuff. code cleanup, *
* but the code became longer (who cares?) *
*pars7 02Jun91 KvGend Now accepts expressions!!! *
* And a limited acception of vars... *
* 06Jun91 KvGend Loop & Until implemented *
*par10 27Jul91 KvGend Skip & EndSkip, and many other improvements*
*par11 11Aug91 KvGend implemented Text (finally) *
* 27Aug91 KvGend Anim. Not implemented, just added *
****************************************************************/
#define PARSER
#include <exec/types.h>
#include "uni4.h" /* the ChemNiMate include */
extern char header[];
extern char footer[];
extern int array[MXNUMB][8];
extern char *tlist[];
extern struct DisplayInfo di;
int values[VALUESMAX]; /*array with return-values */
struct ParserInfo pi =
{0, 1, 0, -1, FALSE, 0, 0};
/***********************prototypes**********/
extern LetItShow (int, int, int);
int rightnr (int, int);
/************************int parser(char *)***/
int
parser (char *regel, int listnr)
{
int i, j, strcount = 0, token;
/******** Tokenizing******/
token = tlist[listnr][0] & 0xFF;
pi.valnr = getvalues (regel, values); /*get values in the line */
pi.error = -1;
if (token != 0) /* check right number of arguments */
rightnr (pi.valnr, tlist[listnr][1] & 0x0f);
if (pi.skip == TRUE)
{ /*handle a skip */
if (token == 0x46)
pi.skip = FALSE;
return (0);
}
/********************* interpreting ******************/
if (pi.error == -1)
switch (token)
{
case 0: /*no token available */
if (pi.datanr) /***** data-line ? *****/
{
if (pi.valnr != 5)
{
pi.error = DATA_ERR;
break;
}
for (i = 0; i < 5; i++)
array[pi.datanr][i] = values[i];
pi.datanr++;
break;
}
pi.error = HEADACHE_ERR;/***** no, headache (==Syntax Error) *****/
break;
case 0x10: /***** data *****/
pi.datanr = values[0];
if (pi.datanr == 0 || pi.datanr >= MXNUMB)
pi.error = VAL_ERR;
break;
case 0x11: /***** EndData *****/
if (pi.datanr != 0)
pi.datanr = 0;
else
pi.error = EDWD_ERR;
break;
case 0x12:
printf ("==> ANIM command used... auto-config to MeSsyDOS NOT IMPLEMENTED YET\n");
break;
case 0x20: /***** Repeat *****/
i = 0;
if (values[0] <= 1)
pi.error = VAL_ERR;
else
i = values[0] + 1024 * pi.linenr;
/* throw the repeatpos on the stack */
stack (ST_PUSH, ST_REPEAT, i);
break;
case 0x21: /***** EndRepeat *****/
i = stack (ST_POP, ST_REPEAT, 0);
if (i != ST_NOST) /* there was a repeat on the stack*/
{
if (i % 1024 > 1)
{
pi.linenr = i / 1024; /* restore to linenr */
stack (ST_PUSH, ST_REPEAT, --i); /* and put it back where it belongs*/
}
break;
}
pi.error = ERWR_ERR;
break;
case 0x22: /***** Loop *****/
/* throw the repeatpos on the stack */
stack (ST_PUSH, ST_LOOP, pi.linenr * 1024 + 0);
break;
case 0x23: /***** Until <1> >= <2> *****/
i = stack (ST_POP, ST_LOOP, 0);
if (i == ST_NOST)
{
pi.error = ERWR_ERR;
break;
}
if (i % 1024 >= INFINITYMAX)
{
pi.error = INFINITY_ERR;
break;
}
if (values[0] < values[1])
{
pi.linenr = i / 1024;
stack (ST_PUSH, ST_LOOP, ++i);
}
break;
case 0x30: /***** Lines on/off*****/
switch (values[0])
{
case ON:
di.modes |= LINES; /* turn lines on */
break;
case OFF:
di.modes &= ~LINES; /* turn lines off */
break;
default:
pi.error = VAL_ERR;
}
break;
case 0x31: /***** Balls On/Off *****/
switch (values[0])
{
case ON:
di.modes |= BALLS;
break;
case OFF:
di.modes &= ~BALLS;
break;
default:
pi.error = VAL_ERR;
}
break;
case 0x32: /***** wait time *****/
for (i = 0; i < values[0]; i++)
WAITFRAME ();
break;
case 0x34: /***** DISPLAYMODE *****/
if (values[0] != 0 && values[0] != 1)
{
pi.error = VAL_ERR;
break;
}
di.modes &= ~31;
di.modes |= values[0] & 31;
break;
case 0x41: /***** DEBUG *****/
for (i = values[0]; i <= values[1]; i++)
{
printf ("\n%3d: ", i);
for (j = 0; j < 8; j++)
printf ("%4d ", array[i][j]);
}
printf ("\n");
break;
case 0x45: /***** Skip *****/
pi.skip = TRUE;
break;
case 0x46: /***** EndSkip *****/
pi.error = NOSKIP_ERR; /* when the program ever gets here, */
break; /* it means that there isn't a SKIP encountered */
case 0x50: /***** Show *****/
if (values[2] < values[1] || values[0] < 1)
pi.error = VAL_ERR;
else
LetItShow (values[0], values[1], values[2]);
break;
case 0x51: /***** ShowNS *****/
if (values[1] < values[0])
pi.error = VAL_ERR;
else
LetItShow (0, values[0], values[1]);
break;
case 0x52: /* SPages */
SwapShow ();
break;
case 0x62: /***** Set MiddleOfScreen (oorsprong)*****/
if (values[0] > VWIDTH || values[0] < 0 || values[1] > VHEIGHT || values[1] < 0)
{
pi.error = VAL_ERR;
break;
}
di.mx = values[0] + LBOR;
di.my = values[1] + UBOR;
break;
case 0x70: /***** THeader *****/
TakeStr (regel, header);
break;
case 0x71: /***** TFooter *****/
TakeStr (regel, footer);
break;
case 0x72:
if (values[0] > VWIDTH || values[0] < 0 || values[1] > VHEIGHT || values[1] < 0)
{
pi.error = VAL_ERR;
break;
}
TakeStr (regel, regel);
TextAt (values[0], values[1], regel);
break;
case 0x73: /***** T *****/
TakeStr (regel, regel);
printf ("#tekst: '%s'\n", regel);
break;
case 0x80: /***** change *****/
case 0x81:
case 0x82:
DoChange (regel, token);
break;
case 0x90: /***** I:= *****/
pi.I = values[0];
break;
case 0x91: /***** J:= *****/
pi.J = values[0];
break;
case 0x92:
case 0x60: /***** ANG:= *****/
di.angle = (values[0] & 63) + 65536;
break;
case 0x93:
case 0x61: /***** DAN:= *****/
if (values[0] > 10 || values[0] < -10)
pi.error = VAL_ERR;
else
di.dangle = values[0];
break;
default:
printf ("$$ This should not occur !!!\nToken : %X Line : %d\n", token, pi.linenr);
}
if (pi.error == -1) /*no error */
return (0);
/*an error occurred */
ErrHand (pi.error, pi.linenr);
} /**************end-of-parser()*/
ErrHand (int which, int nr) /* fout-afhandeling */
{
/* I designed it this way, to keep the error messages issued from one point*/
printf ("%s IN LINE %d\n", errtxt[which], nr);
}
/****************************getvalues(char *line,int *values) *****/
int
getvalues (char *line, int *values)
{
int i = 0, j = 0, q;
/* scan until first value or ;(remark) or ](end-of-expr)*/
for (j = 0; j < strlen (line); j++)
{
if (line[j] == '#') /*begin of a variable */
{
q = gvar (line + j + 1);
if ((values[i++] = q) == FULLCRAZY)
return (-1);
while (line[++j] != '#') ; /*continue till end of varname */
continue;
}
if (line[j] == '[') /*begin of an expression */
{
q = evalexp (line + j + 1);
if ((values[i++] = q) == FULLCRAZY)
return (-1); /*error in evaluating*/
while (line[j] != '@')
j++;
line[j] = '©';
}
if (ISNUM (line[j]))
{ /* it's a value !!*/
values[i++] = atoi (&line[j]);
if (i >= VALUESMAX)
break;
while (ISNUM (line[j]))
j++;
j--;
}
/* stop with getvalues when: */
if (line[j] == ';' || line[j] == '\"' || line[j] == ']')
break;
}
return (i);
}
char *vars[] =
{"I\0", "J\0", "ON\0", "OFF\0", "ANG\0", "DAN\0", "#"};
/*******************************int gvar(char *line) *****/
int
gvar (char *line)
{
char name[8];
int teller = 0, welke;
for (teller = 0; line[teller] != '#' && teller < 3; teller++)
name[teller] = line[teller];/* copy 'line' in 'name' */
name[teller] = 0; /* null-terminate string*/
if (teller > 3)
{
pi.error = VAREND_ERR;
return (FULLCRAZY);
}
for (welke = 0; vars[welke][0] != '#'; welke++)
if (!strcmp (name, vars[welke]))
break;
if (vars[welke][0] == '#')
{
pi.error = NOVAR_ERR;
return (FULLCRAZY); /*not a right name*/
}
switch (welke)
{
case 0: /* I */
return (pi.I);
case 1: /* J */
return (pi.J);
case 2: /* ON */
return (ON);
case 3: /* OFF */
return (OFF);
case 4: /* ANG */
return (di.angle & 63);
case 5: /* DAN */
return (di.dangle & 63);
}
printf ("this should not occur: welke: %d\n", welke);
return (FULLCRAZY); /*HELP!! WE SHOULD NEVER GET THIS FAR!!*/
} /*end-of-gvar() */
/*******************************int evalexp(char *line) *****/
int
evalexp (char *line)
{
int data[VALUESMAX];
int teller, result = FULLCRAZY;
if (getvalues (line, data) == 2)
{
for (teller = 0; teller < strlen (line) && result == FULLCRAZY; teller++)
switch (line[teller])
{
case '*':
result = data[0] * data[1];
break;
case '/':
if (data[1] == 0)
{
pi.error = DIVISION_ERR;
return (FULLCRAZY);
}
result = data[0] / data[1];
break;
case '+':
result = data[0] + data[1];
break;
case '_':
result = data[0] - data[1];
break;
} /* end-of-switch() */
/* remove the operator */
if (result != FULLCRAZY)
line[teller - 1] = '$';
else
pi.error = ITTAKESTWO_ERR; /*shit! no operator*/
/* check and remove the ] */
for (teller = 0; line[teller] != ']' && teller < strlen (line); teller++) ;
if (line[teller] != ']')
{
pi.error = PARENTH_ERR;
result = FULLCRAZY;
}
line[teller] = '@';
} /*end-of-if*/
else
/*not right number of values */
pi.error = ITTAKESTWO_ERR;
return (result);
} /*End-Of-evalexp() */
/**************************TakeStr(char *line,char *desstr)**/
TakeStr (char *line, char *desstr)
{
int teller = 0, pos = 0;
do
{
pos++;
} while (pos <= strlen (line) && line[pos - 1] != '\"');
do
{
desstr[teller++] = line[pos++];
} while (pos <= strlen (line) && line[pos] != '\"');
desstr[teller] = 0;
}
/**************************rightnr(real number,required number)*****/
int
rightnr (int realnr, int reqnr)
{
if (realnr < reqnr)
{
pi.error = TOOFEW_ERR;
errtxt[pi.error][27] = realnr + '0';
errtxt[pi.error][10] = reqnr + '0';
return (1); /* ERROR, line is not executable */
}
if (realnr > reqnr)
{
pi.error = TOOMUCH_ERR;
errtxt[pi.error][31] = reqnr + '0';
return (1); /* ERROR, line is not executable */
}
return (0); /* wow, right number of values */
}
/***********************************DoChange(regel)***********
* The change-group (0x80 - 0x8f)
* C Change
* [R] relative <nr> <type> <add>
* [A] absolute <nr> <type> <value>
* [M] more items relative <from> <upto&including> <type> <add>
*/
DoChange (char *regel, int token)
{
int i;
switch (token)
{
case 0x80:
case 0x81:
if (values[1] > 4 || values[1] < 0
|| values[0] < 0 || values[0] >= MXNUMB)
pi.error = VAL_ERR;
else if (token == 0x80)
array[values[0]][values[1]] += values[2]; /* relative ch. */
else
array[values[0]][values[1]] = values[2]; /*absolute change */
break;
case 0x82:
if (values[1] <= values[0]
|| values[0] < 0
|| values[1] >= MXNUMB
|| values[2] < 0 || values[2] > 4)
pi.error = VAL_ERR; /*INCORRECT VALUE */
else
for (i = values[0]; i <= values[1]; i++)
array[i][values[2]] += values[3];
break;
default:
pi.error = HEADACHE_ERR;
}
}
/**********************************int stack(int code,int value)***
*calling:
* stack(ST_PUSH,id,value) id=(depth+id) of repeat/gosub etc.
* value = stack(ST_POP,id,0); get the value of the stack which represents
* the id (nb: depth is ignored)
* value = stack(ST_QUIT,0,0); if !0, there's garbage on the stack.
*
*/
int
stack (int code, int type, long int value)
{
static int stack[STMAX][2];
static int stkptr = 0;
long int ret;
int tel;
switch (code)
{
case ST_INIT: /* just for symmetry (Teijo, thanks for excuse)*/
break;
case ST_PUSH: /* push something on the stack*/
if (stkptr < STMAX)
{
stack[++stkptr][0] = type;
stack[stkptr][1] = value;
}
break;
case ST_POP:
if (stkptr > 0) /* IS there a stack */
{
for (tel = stkptr; tel > 0; tel--) /* yes, there is a stack */
if (stack[tel][0] == type)
{
ret = stack[tel][1];
stkptr = tel - 1; /* decrease the stkptr -> point to prev */
break; /* break the for */
}
if (tel == 0) /* unfortunately, there's not what we want */
ret = ST_NOST;
} /* end-of-if */
else
ret = ST_NOST; /* no, there ain't a stack */
break;
case ST_QUIT: /* it is wrong when !0 returned */
ret = stkptr;
break;
}
return (ret);
}